#include "LMWorker.h"
#include "../master/LMMaster.h"
#include "../util/transaction.h"
#include "../algorithm/algorithm.h"
#include "../LMContext.h"

LMWorker::LMWorker(boost::shared_ptr<LMContext> context, boost::shared_ptr<LMMaster> master, int index)
	:_master(master)
	,_index(index)
	,_context(context)
{

}

LMWorker::~LMWorker()
{

}

void LMWorker::start()
{
	_worker_thr.reset(new boost::thread(boost::bind(&LMWorker::worker_thread, this)));
}

void LMWorker::worker_thread()
{
	// local work data
	minerRiecoinBlock_t minerRiecoinBlock; 

	while( true )
	{
		// has work?
		bool hasValidWork = false;
		EnterCriticalSection(&(_master->workDataSource.cs_work));
		if( _master->workDataSource.height > 0 )
		{
			switch( _master->workDataSource.algorithm )
			{
			case ALGORITHM_RIECOIN:
				// get maxcoin work data
				memset(&minerRiecoinBlock, 0x00, sizeof(minerRiecoinBlock));
				minerRiecoinBlock.version = _master->workDataSource.version;
				minerRiecoinBlock.nTime = (uint64)time(NULL) + (uint64)(sint64)(sint32)_master->workDataSource.timeBias; // Riecoin uses 64bit timestamp
				minerRiecoinBlock.nBits = _master->workDataSource.nBits;
				minerRiecoinBlock.targetCompact = _master->workDataSource.targetCompact;
				minerRiecoinBlock.shareTargetCompact = _master->workDataSource.shareTargetCompact;
				//minerRiecoinBlock.nonce = 0; // nonce was replaced by nOffset byte[32]
				minerRiecoinBlock.height = _master->workDataSource.height;
				memcpy(minerRiecoinBlock.merkleRootOriginal, _master->workDataSource.merkleRootOriginal, 32);
				memcpy(minerRiecoinBlock.prevBlockHash, _master->workDataSource.prevBlockHash, 32);
				minerRiecoinBlock.uniqueMerkleSeed = _context->uniqueMerkleSeedGenerator;
				_context->uniqueMerkleSeedGenerator++;
				// generate merkle root transaction
				bitclient_generateTxHash(sizeof(uint32), (uint8*)&minerRiecoinBlock.uniqueMerkleSeed, _master->workDataSource.coinBase1Size, _master->workDataSource.coinBase1, _master->workDataSource.coinBase2Size, _master->workDataSource.coinBase2, _master->workDataSource.txHash, TX_MODE_DOUBLE_SHA256);
				bitclient_calculateMerkleRoot(_master->workDataSource.txHash, _master->workDataSource.txHashCount+1, minerRiecoinBlock.merkleRoot, TX_MODE_DOUBLE_SHA256);
				hasValidWork = true;
				break;
			}
		}
		LeaveCriticalSection(&(_master->workDataSource.cs_work));
		if( hasValidWork == false )
		{
			Sleep(1);
			continue;
		}
		// valid work data present, start processing workload
		if( _master->workDataSource.algorithm == ALGORITHM_RIECOIN )
		{
			riecoin_process(&minerRiecoinBlock, _index, _context);
		}
		else
		{
			printf("xptMiner_minerThread(): Unknown algorithm\n");
			Sleep(5000); // dont spam the console
		}
	}
}
